#include <map>
#include <iostream>
#include <cstdlib>
using namespace std;

class MemChecker{
    private:
        class Entry{
            public:
                Entry(const char* file = NULL, long line = 0) : file_(file), line_(line) {}
                inline const char* File() const{
                    return file_;
                }
                inline long Line() {
                    return line_;
                }
            private:
                const char* file_;
                long line_;
        };
    public:
        MemChecker();
        ~MemChecker();
        void Add(void* pointer, const char* file, long line);
        void Remove(void* pointer);
        void Dump();
    public:
        static bool Ready;
    private:
        map<void*, Entry> pointer_map_;
};

MemChecker::MemChecker() {
    MemChecker::Ready = true;
}

MemChecker::~MemChecker() {
    this->Dump();
    MemChecker::Ready = false;
}

void MemChecker::Add(void* pointer, const char* file, long line) {
    this->pointer_map_[pointer] = MemChecker::Entry(file, line);
}

void MemChecker::Remove(void* pointer) {
    map<void*, MemChecker::Entry>::iterator iter = this->pointer_map_.find(pointer);
    if (iter != this->pointer_map_.end()) this->pointer_map_.erase(iter);
}

void MemChecker::Dump() {
    if (!this->pointer_map_.empty()) {
        auto iter = this->pointer_map_.begin();
        while (iter != this->pointer_map_.end()) {
            const char* file = iter->second.File();
            long line = iter->second.Line();
            cout << "file:" << file << "\tline:" << line << " memory leak" << endl;
            ++iter;
        }
    }
}

bool MemChecker::Ready = false;

MemChecker mch;

void* operator new(size_t size, const char* file, long line) {
    void* p = malloc(size);
    if (MemChecker::Ready) {
        mch.Add(p, file, line);
    }
    return p;
}

void operator delete(void* p) {
    if (MemChecker::Ready) {
        mch.Remove(p);
    }
    free(p);
}

void operator delete[] (void* p) {
    if (MemChecker::Ready) {
        mch.Remove(p);
    }
    free(p);
}
